﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Collections.Specialized;
using Cabal.Kernel.Cryptilogy;


namespace Cabal.Kernel.Provider
{
    /// <summary>
    /// 提供加密方式的常数管理类
    /// </summary>
    public class ConstProvider :IDisposable
    {
        public ConstProvider(CabalSoul kernel) : this(kernel, Path_Default) { }
        public ConstProvider(CabalSoul kernel,string path)
        {
            _kernel = kernel;
            _path = path;

            _crypts = new Dictionary<string, ICryptProvider>();
            _items = new List<ConstItem>();
            _decrypted = new Dictionary<string, string>();

            load();
        }


        const string Path_Default = "Const.XML";
        const string Regid_Const = "Const.XML";
        const string XPath_ConstRoot = "CabalSoul/Const";
        const string XPath_ConstItems = "CabalSoul/Const/*";

        Dictionary<string,ICryptProvider> _crypts;  //加密提支持
        Dictionary<string, string> _decrypted;      //已解密编码
        List<ConstItem> _items;                     //常数项目
        CabalSoul _kernel;
        string _path;

        public List<ConstItem> Items
        {
            get { return _items; }
        }


        void init()
        {
            _kernel.Support.Register(Regid_Const,_path);
        }
        void load()
        {
            _kernel.Support.Register(Regid_Const, _path);
            foreach (XmlNode node in _kernel.Support.ReadNode(Regid_Const, XPath_ConstRoot).ChildNodes)
            {
                ConstItem item = new ConstItem(node); //read
                _items.Add(item);  //add
            }
        }
        void unload()
        {
            _items.Clear();
            _decrypted.Clear();
            _crypts.Clear();
            _kernel.Support.UnRegister(Regid_Const);
        }

        public void AddCryptProvider(ICryptProvider crypt)
        {
            string name = crypt.GetName();

            if (_crypts.ContainsKey(name))
                _crypts.Remove(name);

            _crypts.Add(name, crypt);
        }
        public bool RemoveCryptProvider(string name)
        {
            return _crypts.Remove(name);
        }

        public void Reload()
        {
            unload();
            load();
        }
        public bool Decrypt(out List<CryptException> exceptions)
        {
            exceptions = new List<CryptException>();
            bool rtv = true;

            foreach (ConstItem i in _items)
            {
                if (_crypts.ContainsKey(i.CryptMethod))
                {
                    try
                    {
                        ICryptProvider cp = _crypts[i.CryptMethod];
                        i.Key = cp.DecryptStringBase64(i.Key);
                        i.Value = cp.DecryptStringBase64(i.Value);
                        i.Decrypted = true;

                        if (_decrypted.ContainsKey(i.Key))
                            _decrypted.Remove(i.Key);
                        _decrypted.Add(i.Key, i.Value);
                    }
                    catch (Exception err)
                    {
                        CryptException errt = new CryptException("在解密" + i.CryptMethod + "时遇到错误", err);
                        exceptions.Add(errt);
                        rtv = false;
                    }
                }
            }
            return rtv;
        }

        public string GetConst(string key)
        {
            //foreach (ConstItem i in _items)
            //    if (i.Decrypted && i.Key == key)
            //        return i.Value;

            if (_decrypted.ContainsKey(key))
                return _decrypted[key];
            else
                return null;

        }

        /// <summary>
        /// 生成基本的加密类
        /// </summary>
        /// <param name="rsaPublicKey">RSA公钥</param>
        /// <param name="rsaMod">RSA公共模数</param>
        /// <returns></returns>
        public static List<ICryptProvider> BaseCryptProviders(string rsaPublicKey,string rsaMod)
        {
            List<ICryptProvider> lst = new List<ICryptProvider>();

            lst.Add(new CProviderNoncrypt());
            lst.Add(new CProviderRSA(rsaPublicKey, rsaMod));

            return lst;
        }

        /// <summary>
        /// 内置常数项目
        /// </summary>
        public class ConstItem
        {
            public string CryptMethod;
            public string Key;
            public string Value;
            public bool Decrypted = false;

            const string XPath_CryptMethod = "CryptMethod";
            const string XPath_Key = "Key";
            const string XPath_Value = "Value";

            public ConstItem(XmlNode itemNode)
            {
                read(itemNode);
                Decrypted = false;
            }

            void read(XmlNode itemNode)
            {
                XmlNode node;

                node = itemNode.SelectSingleNode(XPath_CryptMethod);
                CryptMethod = node.InnerText;

                node = itemNode.SelectSingleNode(XPath_Key);
                Key = node.InnerText;

                node = itemNode.SelectSingleNode(XPath_Value);
                Value = node.InnerText;
            }
        }

        #region IDisposable 成员

        public void Dispose()
        {
            unload();

             _items = null;
             _decrypted = null;
             _crypts = null;
        }

        #endregion
    }
}